package org.xmppbot.net.nio;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.net.MXParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import org.xmppbot.Connection;
import org.xmppbot.net.nio.BotNIOConnection;
import org.xmppbot.net.StanzaHandler;

/**
 * Обработчик
 * @author stas
 */
class BotSocketIOHandler extends IoHandlerAdapter{

	static final String XML_PARSER = "XML-PARSER";
    private static final String HANDLER = "HANDLER";
    private static final String CONNECTION = "CONNECTION";
	
    private static Map<Integer, XMPPPacketReader> parsers = new ConcurrentHashMap<Integer, XMPPPacketReader>();

    private static final Logger _logger = LoggerFactory.getLogger(BotSocketAcceptor.class);

    /**
     * Reuse the same factory for all the connections.
     */
    private static XmlPullParserFactory factory = null;

    static {
        try {
            factory = XmlPullParserFactory.newInstance(MXParser.class.getName(), null);
            factory.setNamespaceAware(true);
        }
        catch (XmlPullParserException e) {
            _logger.error("Error creating a parser factory", e);
        }
    }
    
	@Override
    public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
    {
        cause.printStackTrace();
        _logger.error("", cause);
    }
	
    @Override
    public void messageReceived( IoSession session, Object message ) throws Exception
    {
        String str = message.toString();
        _logger.debug("SOCKET IN: "+str);
//        session.write("<stream:stream xmlns:stream='http://etherx.jabber.org/streams' " +
//        							 "xmlns='jabber:server' " +
//        							 "xmlns:db='jabber:server:dialback' "+
//        							 "id='12345'"+
//        		">");
        StanzaHandler handler = (StanzaHandler) session.getAttribute(HANDLER);
        
        /**
         * Как я понимаю к каждому обработчику IoHandler прикрепляется собственный xmpp reader
         */
        int hashCode = Thread.currentThread().hashCode();
        XMPPPacketReader parser = parsers.get(hashCode);
        if (parser == null) {
            parser = new XMPPPacketReader();
            parser.setXPPFactory(factory);
            parsers.put(hashCode, parser);
        }
        try{
        	handler.process((String)message, parser);
        }catch (Exception e){
        	_logger.error("", e);
        	Connection connection = (Connection) session.getAttribute(CONNECTION);
        	connection.close();
        }
        
    }

    @Override
    public void sessionCreated(IoSession session) throws Exception {
    	super.sessionCreated(session);
    	_logger.debug("НОВАЯ СЕССИЯ: "+session.getId());

    	Connection connection = new BotNIOConnection(session);
    	session.setAttribute(CONNECTION, connection);
//    	session.setAttribute(HANDLER, new StanzaHandlerImpl(connection));
    	session.setAttribute(IdleStatus.READER_IDLE, 10*60*1000);
    }
    @Override
    public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
    {
    	Connection connection = (Connection)session.getAttribute(CONNECTION);
    	connection.close();
    }

    @Override
    public void messageSent(IoSession session, Object message) throws Exception {
    	super.messageSent(session, message);
    	_logger.debug("SOCKET OUT: "+message.toString());
    }
}
